﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace GOFconsole
{
    public class Chapter24_ChainOfResposibility
    {
        public void COR_Test()
        { 
            //模型
            Handler h1 = new ConcreteHandler1();
            Handler h2 = new ConcreteHandler2();
            Handler h3 = new ConcreteHandler3();
            h1.SetSuccessor(h2);
            h2.SetSuccessor(h3);

            int[] requests = { 1, 5, 10, 18, 19, 3, 29 };
            foreach (var item in requests)
            {
                h1.HandlerRequest(item);
            }

            //DEMO
            CommonManager jingli = new CommonManager("经理甲");
            Majordomo zongjian = new Majordomo("总监乙");
            GeneralManager zongjingli = new GeneralManager("总经理丙");
            //设置上级
            jingli.SetSuperior(zongjian);
            zongjian.SetSuperior(zongjingli);

            Request r1 = new Request { RequestType = "请假", RequestContent = "小菜请假", Number = 1 };
            Request r2 = new Request { RequestType = "请假", RequestContent = "小菜请假", Number = 4 };
            Request r3 = new Request { RequestType = "加薪", RequestContent = "小菜请求加薪", Number = 500 };
            Request r4 = new Request { RequestType = "加薪", RequestContent = "小菜请求加薪", Number = 1500 };

            //申请都是发送给经理，但实际谁来决策由具体管理类来处理，客户端不知道
            jingli.RequestApplications(r1);
            jingli.RequestApplications(r2);
            jingli.RequestApplications(r3);
            jingli.RequestApplications(r4);
        }
    }

    #region 模型
    abstract class Handler
    {
        protected Handler successor;
        public void SetSuccessor(Handler successor)   //设置继任者
        {
            this.successor = successor;
        }

        public abstract void HandlerRequest(int request);   //处理请求的抽象方法
    }
    //具体处理类，处理它所负责的请求，可访问它的后继者。如果可处理该请求就处理之，否则就将请求转发给后继者
    class ConcreteHandler1 : Handler    
    {
        public override void HandlerRequest(int request)
        {
            if (request >= 0 && request < 10)   //处理者1只负责0-9，不在此范围就传递
            {
                Console.WriteLine("{0}处理请求{1}",this.GetType().Name,request);
            }
            else if (successor != null)
            {
                successor.HandlerRequest(request);  //转移到下一位处理
            }
        }
    }
    class ConcreteHandler2 : Handler
    {
        public override void HandlerRequest(int request)
        {
            if (request >= 10 && request < 20)   //处理者2只负责10-19，不在此范围就传递
            {
                Console.WriteLine("{0}处理请求{1}", this.GetType().Name, request);
            }
            else if (successor != null)
            {
                successor.HandlerRequest(request);  //转移到下一位处理
            }
        }
    }
    class ConcreteHandler3 : Handler
    {
        public override void HandlerRequest(int request)
        {
            if (request >= 20 && request < 30)   //处理者2只负责20-29，不在此范围就传递
            {
                Console.WriteLine("{0}处理请求{1}", this.GetType().Name, request);
            }
            else if (successor != null)
            {
                successor.HandlerRequest(request);  //转移到下一位处理
            }
        }
    }

    #endregion

    #region Demo(请假和加薪)
    class Request
    {
        public string RequestType { get; set; }
        public string RequestContent { get; set; }
        public int Number { get; set; }
    }

    abstract class Manager
    {
        protected string name;
        protected Manager superior; //管理者的上级

        public Manager(string name)
        {
            this.name = name;
        }
        public void SetSuperior(Manager superior)   //**关键方法，设置管理者的上级
        {
            this.superior = superior;
        }

        abstract public void RequestApplications(Request request);
    }
    class CommonManager : Manager   //经理
    {
        public CommonManager(string name)
            : base(name)
        { }        

        public override void RequestApplications(Request request)
        {
            if (request.RequestType == "请假" && request.Number <= 2)//经理只能许可2天请假
            {
                Console.WriteLine("{0}:{1} 数量{2} 被批准", name, request.RequestContent, request.Number);
            }
            else 
            {
                if (superior != null)
                {
                    superior.RequestApplications(request);
                }
            }
        }
    }
    class Majordomo : Manager
    {
        public Majordomo(string name)
            : base(name)
        { }

        public override void RequestApplications(Request request)
        {
            if (request.RequestType == "请假" && request.Number <= 5) //总监可以许可一周的假期
            {
                Console.WriteLine("{0}:{1} 数量{2} 被批准", name, request.RequestContent, request.Number);
            }
            else
            {
                if (superior != null)
                {
                    superior.RequestApplications(request);
                }
            }
        }
    }
    class GeneralManager : Manager
    {
        public GeneralManager(string name)
            : base(name)
        { }

        public override void RequestApplications(Request request)
        {
            if (request.RequestType == "请假" ) //总经理可以许可任意假期
            {
                Console.WriteLine("{0}:{1} 数量{2} 被批准", name, request.RequestContent, request.Number);
            }
            else if (request.RequestType == "加薪" && request.Number <= 500)
            {
                Console.WriteLine("{0}:{1} 数量{2} 被批准", name, request.RequestContent, request.Number);
            }
            else if (request.RequestType == "加薪" && request.Number > 500)
            {
                Console.WriteLine("{0}:{1} 数量{2} 再说吧", name, request.RequestContent, request.Number);
            }
        }
    }

    #endregion
}
